#include <iostream>
#include <functional>
#include <vector>
#include <cstdint>
#include <memory>
#include <unordered_map>
#include <unistd.h>

using TaskFunc = std::function<void()>;
using ReleaseFunc = std::function<void()>; 
// 定时任务类
class TimerTask 
{
private:
    uint64_t m_id;
    uint32_t m_timerefresh;
    TaskFunc m_task;
    ReleaseFunc m_release;
    bool m_canceled; //  定时任务是否被取消 --- 不能再时间轮中取消，因为这样的话相当于是提前执行了
public:
    TimerTask(uint64_t id, uint32_t timerefresh, TaskFunc task)
        :m_id(id)
        ,m_timerefresh(timerefresh)
        ,m_task(task)
        ,m_canceled(false)
    {}
    void Cancel()
    {
        m_canceled = true;
    }
    void SetReleaseFuc(const ReleaseFunc& release)
    {
        m_release = release;
    }
    uint32_t Delay()
    {
        return m_timerefresh;
    }
    ~TimerTask()
    {
        if (m_canceled == false)
            m_task();
        m_release();
    }
};

class TimerWheel
{
private:
    using PtrTask = std::shared_ptr<TimerTask>;
    using WeakTask = std::weak_ptr<TimerTask>;
    int m_tick;
    int m_capacity;
    std::vector<std::vector<PtrTask>> m_wheel;
    std::unordered_map<uint64_t, WeakTask> m_timers;
private:
    void RemoveTimer(uint32_t id)
    {
        auto it = m_timers.find(id);
        if (it != m_timers.end())
        {
            m_timers.erase(it);
        }
    }
public:
    TimerWheel()
        :m_tick(0)
        ,m_capacity(60)
        ,m_wheel(m_capacity) 
    {}
    void TimerAdd(uint64_t id, uint32_t delaytime, TaskFunc task)
    {
        // 构建延时任务类
        PtrTask sp(new TimerTask(id, delaytime, task)); // 构建sharedptr，插入表盘中
        sp->SetReleaseFuc(std::bind(&TimerWheel::RemoveTimer, this, id));
        WeakTask wp(sp); // 构建weakptr，插入所有的延时队列中
        // 添加任务
        int inserti = (delaytime + m_tick) % m_capacity;
        m_wheel[inserti].push_back(sp);
        m_timers[id] = wp;
    }
    void TimerRefresh(uint64_t id)
    {
        auto it = m_timers.find(id);
        if (it == m_timers.end())
            return;
        PtrTask sp = it->second.lock();
        int inserti = (m_tick + sp->Delay()) % m_capacity;
        m_wheel[inserti].push_back(sp);
    }
    void TimerCancel(uint64_t id)
    {
        auto it = m_timers.find(id);
        if (it == m_timers.end())
            return;
        PtrTask sp = it->second.lock();
        sp->Cancel();
    }
    void TimerRun()
    {
        m_tick = (m_tick + 1) % m_capacity;
        m_wheel[m_tick].clear();
    }
    ~TimerWheel()
    {}
};


class Test
{
public:
    Test() { std::cout << "Test" << std::endl; }
    ~Test() { std::cout << "~Test" << std::endl; }
};

void Delete(Test *t)
{
    delete t;
}

int main()
{
    TimerWheel tw;
    Test *t = new Test();

    tw.TimerAdd(888, 5, std::bind(Delete, t));

    for (int i = 0; i < 5; i++)
    {
        tw.TimerRefresh(888);
        tw.TimerRun();
        std::cout << "刷新了定时任务, 需要5s后销毁" << std::endl;
    }

    while (1)
    {
        sleep(1);
        std::cout << "-----------------" << std::endl;
        tw.TimerRun();
    }
    return 0;
}